package com.googlecode.linkmein.domain;

import net.sf.jml.*;
import net.sf.jml.event.MsnAdapter;
import net.sf.jml.event.MsnContactListAdapter;
import net.sf.jml.impl.MsnMessengerFactory;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class MSN implements InstantMessenger {

    private String email;

    private String password;


    public MSN(String email, String password) {
        this.email = email;
        this.password = password;
    }

    public String getUserName() {
        return email;
    }

    public static MSN get(String userName, String password) {
        return new MSN(userName, password);
    }

    public void start() {
        MsnMessenger messenger;
        messenger = MsnMessengerFactory.createMsnMessenger(email,
                password);
        messenger.getOwner().setInitStatus(MsnUserStatus.ONLINE);
        messenger.setLogIncoming(true);

        messenger.setLogOutgoing(true);
        messenger.addListener(new MsnAdapter() {
            @Override
            public void loginCompleted(MsnMessenger messenger) {
                messenger.addFriend(Email.parseStr("zeeho_81@hotmail.com"), "TEST");
            }
        });
        messenger.login();

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        messenger.logout();
    }


    public Result login() throws Exception {
        Result result = null;
        MsnMessenger messenger = null;
        try {
            messenger = MsnMessengerFactory.createMsnMessenger(email, password);
            messenger.getOwner().setInitStatus(MsnUserStatus.ONLINE);
            messenger.setLogIncoming(true);
            messenger.setLogOutgoing(true);
            MyMsnContactListAdapter adapter = new MyMsnContactListAdapter();
            messenger.addContactListListener(adapter);

            messenger.login();

            result = new Result(ResultType.SUCCESSFUL, "Login successfully.");
        } catch (Exception e) {
            result = new Result(ResultType.FAILED, "Failed to Login.");
        } finally {
            try {
                if (messenger != null) {
                    messenger.logout();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public Employee find(Employees employees) {
        for (Employee employee : employees) {
            if (StringUtils.equalsIgnoreCase(employee.getMSN(), this.getUserName())) {
                return employee;
            }
        }
        return Employee.NULL;
    }

    public void initialize(Employee employee) {
        employee.setMsn(email);
    }

    public Result inviteFriend(final Employee employee) throws InterruptedException {
        String groupName = employee.getProject().getName();
        Result result = null;
        MsnMessenger messenger = null;
        MyMsnAdapter listener = new MyMsnAdapter(employee, groupName);
        try {
            messenger = MsnMessengerFactory.createMsnMessenger(email, password);
            messenger.getOwner().setInitStatus(MsnUserStatus.ONLINE);
            messenger.setLogIncoming(true);
            messenger.setLogOutgoing(true);
            messenger.addListener(listener);
            messenger.login();
            waitForAddingFinished(listener, 40000);
            result = new Result(ResultType.SUCCESSFUL, "Login successfully.");
        } catch (Exception e) {
            result = new Result(ResultType.FAILED, "Failed to Login.");
        } finally {
            try {
                if (messenger != null) {
                    messenger.logout();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

//    public static void main(String[] args) throws InterruptedException {
//        MSN msn = new MSN("", "");
//        Contact contact = new Contact("hukai", null, "zeeho_81@hotmail.com", null, null);
//        Result result = msn.inviteFriend(new Employee(contact, new Resource(new Name("hu kai", "hu kai"), "dev", "")), "Cruise");
//        System.out.println(result.isSuccess());
//    }

    private void waitForAddingFinished(MyMsnAdapter listener, int timeout) throws InterruptedException {
        long spentTime = 0;
        while (spentTime < timeout) {
            if (listener.isAdded()) {
                return;
            }
            spentTime += 100;
            Thread.sleep(100);
        }
        throw new RuntimeException("Failed to load your friends in reasonable time");
    }

    public List<String> getFriends() throws InterruptedException {
        MsnMessenger messenger = MsnMessengerFactory.createMsnMessenger(email, password);
        messenger.getOwner().setInitStatus(MsnUserStatus.ONLINE);
        messenger.setLogIncoming(true);
        messenger.setLogOutgoing(true);
        messenger.addListener(new MsnAdapter());
        final MyMsnContactListAdapter adapter = new MyMsnContactListAdapter();

        messenger.login();
        messenger.addContactListListener(adapter);
        return getFriends(adapter, 40000);
    }

    private List<String> getFriends(MyMsnContactListAdapter adapter, long timeout) throws InterruptedException {
        long spentTime = 0;
        while (spentTime < timeout) {
            if (adapter.isInitid()) {
                return adapter.getFriends();
            }
            spentTime += 100;
            Thread.sleep(100);
        }
        throw new RuntimeException("Failed to load your friends in reasonable time");
    }


    class MyMsnAdapter extends MsnAdapter {
        boolean added = false;
        private Employee employee;
        private String groupName;

        public MyMsnAdapter(Employee employee, String groupName) {
            this.employee = employee;
            this.groupName = groupName;
        }

        @Override
        public void contactAddCompleted(MsnMessenger messenger, MsnContact contact) {
            added = true;
        }

        @Override
        public void loginCompleted(MsnMessenger messenger) {
            messenger.addFriend(Email.parseStr(employee.getMSN()), groupName);
        }

        public boolean isAdded() {
            return added;
        }
    }

    class MyMsnContactListAdapter extends MsnContactListAdapter {
        private boolean isInited = false;
        private List<String> friends = new ArrayList<String>();

        public void contactStatusChanged(MsnMessenger msn, MsnContact con) {

        }

        public void contactListInitCompleted(MsnMessenger messenger) {
            MsnContact[] msnContacts = messenger.getContactList().getContactsInList(MsnList.FL);
            for (MsnContact msnContact : msnContacts) {
                friends.add(msnContact.getEmail().getEmailAddress());
            }
            isInited = true;
        }

        public boolean isInitid() {
            return isInited;
        }

        public List<String> getFriends() {
            return friends;
        }
    }
}